<template>
  <div class="os-main">
    <ConfigForm v-model="dataForm" :config="config" ref="configFormRef" />

    <el-button type="primary" @click="onSubmit" :disabled="config.mode === 'look'">提交</el-button>
    <el-button type="primary" @click="reRenderC">重新渲染</el-button>
    <el-button type="primary" @click="switchMode">切换模式</el-button>
    <el-button type="primary" @click="openJson">查看表单数据</el-button>
    <el-button @click="onCancel">取消</el-button>

    <el-drawer v-model="drawerVisiable" title="数据视图" :direction="'rtl'" size="40%">
      <CodeView :code-json="JSON.stringify(dataForm, null, '\t')"></CodeView>
    </el-drawer>
  </div>
</template>

<script lang="ts" setup>
import { ElMessage, ElButton, ElDrawer, ElCheckbox, ElRadio } from 'element-plus'
import type { Config } from '@/components/ConfigForm'
import formValidate from '@/utils/formValidate'
import CodeView from '@/components/CodeView/index.vue'
import PopupSelect from '@/components/PopupSelect/index.vue'
import { getTableData } from '@/api/index'
import { ref, markRaw, h } from 'vue'
import ConfigForm from '@/components/ConfigForm/index'

const shortcuts = [
  {
    text: '今天',
    value: new Date(),
  },
  {
    text: '昨天',
    value: () => {
      const date = new Date()
      date.setTime(date.getTime() - 3600 * 1000 * 24)
      return date
    },
  },
  {
    text: '上周',
    value: () => {
      const date = new Date()
      date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
      return date
    },
  },
]
const rangeShortcuts = [
  {
    text: '最近一周',
    value: () => {
      const end = new Date()
      const start = new Date()
      start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
      return [start, end]
    },
  },
  {
    text: '最近一月',
    value: () => {
      const end = new Date()
      const start = new Date()
      start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
      return [start, end]
    },
  },
  {
    text: '最近三月',
    value: () => {
      const end = new Date()
      const start = new Date()
      start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
      return [start, end]
    },
  },
]
const disabledDate = (time: Date) => {
  return time.getTime() > Date.now()
}
const defaultTimeRange = [
  new Date(2000, 1, 1, 0, 0, 0),
  new Date(2000, 1, 1, 23, 59, 59)
]
const checkboxOptions = [
  { label: '上海', value: 'Shanghai' },
  { label: '北京', value: 'Beijing' },
  { label: '广州', value: 'Guangzhou', disabled: true },
  { label: '深圳', value: 'Shenzhen' }
]
const radioOptions = [
  { label: '管理员', value: 'admin' },
  { label: '访客', value: 'visitor' },
]
/**ConfigForm绑定对象 */
const dataForm = ref<ObjectAny>({})

/**ConfigForm配置 */
const config = ref<Config>({
  mode: 'add',
  formProps: {},
  rowProps: {},
  columns: [
    { prop: 'username', label: '用户名', type: 'input', rules: [{ required: true }] },
    { // 密码
      prop: 'password', label: '密码', type: 'input',
      rules: [
        { validator: formValidate({ type: 'required', params: ['密码不能为空', (errMsg: string) => { console.log('校验失败回调', errMsg) }] }) }, // 如果需要带回调方法的必填校验，把此规则加在required规则前面
        { required: true },
        { validator: formValidate({ type: 'password', errCallBack: (errMsg: string) => { console.log('校验失败回调', errMsg) } }) },
      ],
    },
    { // 性别
      prop: 'sex', label: '性别', value: '1', type: 'select',
      options: [{ label: '男', value: '1' }, { label: '女', value: '2' }],
      rules: [{ required: true }],
    },
    { // 生日
      prop: 'birthday', label: '生日', type: 'datePicker', value: '2000-11-12',
      props: { type: 'date', valueFormat: 'YYYY-MM-DD', shortcuts, disabledDate }
    },
    { prop: 'status', label: '启用', type: 'switch', value: true },
    { // 联系人
      prop: 'contacts', label: '联系人', type: 'custom', is: markRaw(PopupSelect),
      props: {
        multiple: true,
        queryMethod: getTableData,
        queryData: { pageSize: 5, pageNum: 1 },
        tableColumns: [
          { prop: 'name', label: '姓名', minWidth: '200' },
          { prop: 'sex', label: '性别', align: 'center' },
          { prop: 'age', label: '年龄', align: 'center' }
        ],
        tableSearchList: [
          { prop: 'name', label: '姓名' },
          { prop: 'sex', label: '性别', options: [{ label: '男', value: '1' }, { label: '女', value: '2' }] },
        ]
      },
      events: {
        'update:modelValue': (data: ObjectAny[]) => {
          if (data.length) {
            dataForm.value.contacts = data.map(item => {
              if (!item.id) return item
              return { name: item.name, id: item.id }
            })
          } else {
            dataForm.value.contacts = []
          }
        }
      }
    },
    { // 常驻城市
      prop: 'city', label: '常驻城市', type: 'checkboxGroup',
      events: {
        change: (val: string[]) => { // 通过选框label获取真实的值
          let realValue: any[] = []
          val.forEach((item: string) => {
            const target = checkboxOptions.find(o => o.label === item)
            target ? realValue.push(target.value) : ''
          })
          dataForm.value.cityValue = realValue
        }
      },
      slots: { default: h('div', {}, checkboxOptions.map(item => h(ElCheckbox, item, ''))) }
    },
    { // 角色
      prop: 'role', label: '角色', type: 'radioGroup',
      events: {
        change: (val: string) => { // 通过选框label获取真实的值
          const target = radioOptions.find(o => o.label === val)
          dataForm.value.roleValue = target?.value
        }
      },
      slots: { default: h('div', {}, radioOptions.map(item => h(ElRadio, item, ''))) }
    },
    { // 仅展示的数据
      prop: 'view',
      label: '仅展示',
      value: '这是仅展示的数据',
      type: 'view',
    },
    { // 游戏昵称（分组）
      label: '游戏昵称分组',
      columns: [
        { prop: 'gameName_minecraft', label: 'minecraft昵称', type: 'input', value: 'Carrey', colProps: { span: 6 } },
        { prop: 'gameName_LOL', label: 'LOL昵称', type: 'input', colProps: { span: 6 } },
      ]
    },
    { // 生效时间
      prop: 'effectiveTimeInterval', label: '生效时间', type: 'datePicker',
      props: {
        type: 'datetimerange',
        valueFormat: "YYYY-MM-DD HH:mm:ss",
        shortcuts: rangeShortcuts,
        disabledDate,
        defaultTime: defaultTimeRange,
        rangeSeparator: '至',
        startPlaceholder: '开始日期',
        endPlaceholder: '结束日期'
      }
    },
    { prop: 'remark', label: '备注', type: 'input', colProps: { span: 24 }, props: { type: 'textarea' } },
  ]
})
// 提交
const btnLoading = ref(true)
const configFormRef = ref()
const onSubmit = async () => {
  let submitFlag = true
  btnLoading.value = true

  const valid = await configFormRef.value.mainRef.validate().catch((err: any[]) => err)
  if (valid !== true && submitFlag) {
    // configFormRef.value.mainRef.validateField(Object.keys(valid)[0]) // 重新校验首个错误元素
    configFormRef.value.$el.querySelector('.is-error .el-input__inner').focus() // 聚焦首个错误元素
    submitFlag = false
    ElMessage.closeAll()
    ElMessage.error('校验失败')
  }

  if (submitFlag) {
    ElMessage.closeAll()
    ElMessage.success('校验成功')
  } else {
    btnLoading.value = false
  }
}

// 取消
const onCancel = () => {
  configFormRef.value.mainRef.clearValidate()
}

// 重新渲染ConfigForm
const reRenderC = () => {
  configFormRef.value.reRender()
}

// 切换ConfigForm展示模式
const switchMode = () => {
  if (config.value.mode === 'add') config.value.mode = 'edit'
  else if (config.value.mode === 'edit') {
    config.value.mode = 'look'
    configFormRef.value.mainRef.clearValidate()
  }
  else if (config.value.mode === 'look') config.value.mode = 'add'
  ElMessage.closeAll()
  ElMessage.success(`当前模式：${config.value.mode}`)
}

// 数据视图
const drawerVisiable = ref(false)
const openJson = () => {
  drawerVisiable.value = true
}
</script>
